import cv2
import numpy as np
import pyautogui
import time

class RegionMonitor:
    def __init__(self, regions_config, click_position=(0,0), check_interval=0.2, display_scale=1.0):
        """
        支持显示比例调整的多区域监控系统
        :param regions_config: 区域配置列表
        :param click_position: 基于主区域的相对点击坐标
        :param check_interval: 检测间隔（秒）
        :param display_scale: 窗口显示比例（1.0为原始大小）
        """
        # 主监控区域定义（屏幕绝对坐标）
        self.main_roi = (475, 330, 950, 430)  # (x, y, width, height)
        self.display_scale = display_scale
        
        # 初始化监控区域
        self.monitors = []
        for cfg in regions_config:
            # 坐标转换：相对坐标 → 绝对坐标
            abs_tl = (
                self.main_roi[0] + cfg['top_left'][0],
                self.main_roi[1] + cfg['top_left'][1]
            )
            abs_br = (
                self.main_roi[0] + cfg['bottom_right'][0],
                self.main_roi[1] + cfg['bottom_right'][1]
            )
            
            self.monitors.append({
                'name': cfg['name'],
                'rel_roi': (cfg['top_left'], cfg['bottom_right']),
                'abs_roi': (abs_tl, abs_br),
                'template': self._load_template(cfg['template_path']),
                'threshold': cfg['threshold'],
                'last_state': False
            })
        
        # 点击坐标转换
        self.click_pos = (
            self.main_roi[0] + click_position[0],
            self.main_roi[1] + click_position[1]
        )
        
        # 初始化计时器
        self.check_interval = check_interval
        self.last_click_time = 0
        
        # 创建显示窗口
        self.window_name = "Region Monitor"
        cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL)
        self._resize_window()

    def _load_template(self, path):
        """加载并预处理模板图像"""
        template = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
        if template is None:
            raise FileNotFoundError(f"Template not found: {path}")
        return cv2.GaussianBlur(template, (3,3), 0)

    def _resize_window(self):
        """根据显示比例调整窗口尺寸"""
        scaled_w = int(self.main_roi[2] * self.display_scale)
        scaled_h = int(self.main_roi[3] * self.display_scale)
        cv2.resizeWindow(self.window_name, scaled_w, scaled_h)

    def _capture_main_region(self):
        """捕获主监控区域图像"""
        x, y, w, h = self.main_roi
        screen = pyautogui.screenshot(region=(x, y, w, h))
        return cv2.cvtColor(np.array(screen), cv2.COLOR_RGB2GRAY), \
               cv2.cvtColor(np.array(screen), cv2.COLOR_RGB2BGR)

    def _match_template(self, screen, template, scales=[0.8, 0.9, 1.0, 1.1]):
        """多尺度模板匹配"""
        best_val = -1
        best_scale = 1.0
        best_loc = None
        
        for scale in scales:
            resized = cv2.resize(template, None, fx=scale, fy=scale)
            if resized.shape[0] > screen.shape[0] or resized.shape[1] > screen.shape[1]:
                continue
                
            result = cv2.matchTemplate(screen, resized, cv2.TM_CCOEFF_NORMED)
            _, max_val, _, max_loc = cv2.minMaxLoc(result)
            
            if max_val > best_val:
                best_val = max_val
                best_loc = max_loc
                best_scale = scale
                
        return best_val, best_loc, best_scale

    def _draw_debug_info(self, display, monitor, result):
        """在显示画面上绘制调试信息"""
        (rx1, ry1), (rx2, ry2) = monitor['rel_roi']
        
        # 转换为显示坐标系
        x1 = int(rx1 * self.display_scale)
        y1 = int(ry1 * self.display_scale)
        x2 = int(rx2 * self.display_scale)
        y2 = int(ry2 * self.display_scale)
        
        # 绘制区域框
        cv2.rectangle(display, (x1, y1), (x2, y2), 
                     (0, 255, 255), int(2 * self.display_scale))
        
        if result['matched']:
            # 计算匹配点位置
            pt_x = int((rx1 + result['rel_position'][0]) * self.display_scale)
            pt_y = int((ry1 + result['rel_position'][1]) * self.display_scale)
            
            # 绘制匹配点和文本
            cv2.circle(display, (pt_x, pt_y), 
                      int(5 * self.display_scale), (0, 255, 0), -1)
            text_scale = 0.7 * self.display_scale
            cv2.putText(display, 
                       f"{monitor['name']}: {result['confidence']:.2f}",
                       (x1 + int(10*self.display_scale), y1 + int(30*self.display_scale)),
                       cv2.FONT_HERSHEY_SIMPLEX, text_scale, 
                       (0, 255, 0), int(2 * self.display_scale))
        else:
            text_scale = 0.7 * self.display_scale
            cv2.putText(display, f"{monitor['name']}: Not Found",
                       (x1 + int(10*self.display_scale), y1 + int(30*self.display_scale)),
                       cv2.FONT_HERSHEY_SIMPLEX, text_scale,
                       (0, 0, 255), int(2 * self.display_scale))

    def run(self):
        """启动监控主循环"""
        try:
            while True:
                start_time = time.time()
                
                # 捕获主区域图像
                main_gray, main_display = self._capture_main_region()
                
                # 创建缩放后的显示画面
                scaled_display = cv2.resize(main_display, 
                                           (int(self.main_roi[2] * self.display_scale),
                                            int(self.main_roi[3] * self.display_scale)))
                
                trigger_click = False
                for monitor in self.monitors:
                    # 提取子区域
                    (rx1, ry1), (rx2, ry2) = monitor['rel_roi']
                    sub_region = main_gray[ry1:ry2, rx1:rx2]
                    
                    # 模板匹配
                    confidence, loc, scale = self._match_template(sub_region, monitor['template'])
                    current_state = confidence >= monitor['threshold']
                    
                    # 状态检测
                    print(f"[{monitor['name']}] {'Found' if current_state else 'Empty'} "
                         f"| Conf: {confidence:.2f} | Scale: {scale:.2f}")
                    
                    if not current_state and monitor['last_state']:
                        print(f"!! {monitor['name']} 状态变化 → 触发点击 !!")
                        trigger_click = True
                    
                    monitor['last_state'] = current_state
                    
                    # 绘制调试信息
                    self._draw_debug_info(scaled_display, monitor, {
                        'matched': current_state,
                        'confidence': confidence,
                        'rel_position': loc if loc else (0, 0),
                        'scale': scale
                    })
                
                # 执行点击操作
                if trigger_click and (time.time() - self.last_click_time) > 1.0:
                    pyautogui.click(*self.click_pos)
                    self.last_click_time = time.time()
                    print(f"执行点击 @ {self.click_pos}")
                
                # 显示画面
                cv2.imshow(self.window_name, scaled_display)
                
                # 控制循环频率
                elapsed = time.time() - start_time
                wait_ms = max(1, int((self.check_interval - elapsed) * 1000))
                if cv2.waitKey(wait_ms) == 27:  # ESC退出
                    break
                    
        finally:
            cv2.destroyAllWindows()

if __name__ == "__main__":
    # 示例配置（可根据实际需求修改）
    config = {
        'regions_config': [
            {
                'name': 'Steak Area 1',
                'top_left': (400, 250),
                'bottom_right': (500, 330),
                'template_path': 'exam/game/templates/empty1.png',
                'threshold': 0.7
            },
            {
                'name': 'Steak Area 2',
                'top_left': (520, 256),  # 326-70=256
                'bottom_right': (634, 344),  # 974-360=614, 414-70=344
                'template_path': 'exam/game/templates/empty2.png',
                'threshold': 0.7
            }
        ],
        'click_position': (590, 730),  # 950-360=590, 800-70=730
        'check_interval': 0.3,
        'display_scale': 0.5  # 显示比例设置为150%
    }
    
    monitor = RegionMonitor(**config)
    monitor.run()